package hu.monitor.server.remoting;

import hu.monitor.agent.Test;
import hu.monitor.remoting.InterceptorChain;
import hu.monitor.remoting.InvocationProxyFactory;
import hu.monitor.remoting.client.RemoteCallInterceptor;
import hu.monitor.remoting.transport.Client;
import hu.monitor.remoting.transport.ClientPool;
import hu.monitor.remoting.transport.Marshaller;
import hu.monitor.remoting.transport.socket.SocketClient;
import hu.monitor.server.AgentNotFoundException;
import hu.monitor.server.agent.AgentRepository;
import hu.monitor.server.db.Agent;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

@ApplicationScoped
public class AgentClientProxyFactory {
	@Inject
	private AgentRepository repository;

	@Inject
	private Marshaller marshaller;

	public Test getTest(final int agentId) throws AgentNotFoundException {
		return this.newProxy(Test.class, agentId);
	}

	private <T> T newProxy(final Class<T> remoteInterface, final int agentId) throws AgentNotFoundException {
		final SocketAddress clientAddress = this.getEndpointAddress(agentId);

		final Client client = new SocketClient(this.marshaller, clientAddress);
		final ClientPool pool = new ObjectHolderClientPool(client);
		final RemoteCallInterceptor remote = new RemoteCallInterceptor(pool);
		final InterceptorChain chain = new InterceptorChain(Arrays.asList(remote));
		final InvocationProxyFactory factory = new InvocationProxyFactory(remoteInterface, chain);
		return factory.newProxy();
	}

	private SocketAddress getEndpointAddress(final int agentId) throws AgentNotFoundException {
		final Agent agent = this.repository.findById(agentId);

		String address = agent.getEndpointAddress();
		address = address.substring("socket://".length());
		final String[] split = address.split(":");
		return new InetSocketAddress(split[0], Integer.parseInt(split[1]));
	}
}
